﻿Imports RapidConsole

Public Class MenuWindow
    Inherits Window
    Public Event ItemSelected As EventHandler
    Public Event SelectedIndexChanged As EventHandler

    Private indexChange As Action

    Public ReadOnly Property Item(index As Integer) As String
        Get
            If index > -1 AndAlso index < Content.WordCount Then
                Dim result = Content.GetWordText(Content.Words(index))
                If result.StartsWith(Content.WordSeperator) Then result = result.Substring(1)
                Return result.Trim
            End If
            Return String.Empty
        End Get
    End Property

    Private _SelectedIndex As Integer = -1
    Public Property SelectedIndex As Integer
        Get
            Return _SelectedIndex
        End Get
        Set(value As Integer)
            _SelectedIndex = value
        End Set
    End Property

    Public Sub New(x As Integer, y As Integer, width As Integer)
        MyBase.New(x, y, width, 3)
        Content.WordSeperator = "|"c
    End Sub

    Public Sub Add(item As String)
        If Content.TextLength > 0 Then
            AppendText(Content.WordSeperator & item)
        Else
            AppendText(item)
        End If
    End Sub

    Public Sub RemoveAt(index As Integer)
        If index > -1 Then
            Dim lines As New List(Of String)(Content.Words)
            If index < lines.Count Then
                lines.RemoveAt(index)
                Content.Text = String.Join(Content.WordSeperator, lines.ToArray)
            End If
            _SelectedIndex = index - 1
        End If
    End Sub

    Protected Overrides Function GetBackcolor(x As Integer, y As Integer) As ConsoleColor
        x -= ClientBounds.Left
        Dim p = Parent
        While p IsNot Nothing
            x -= p.Bounds.Left
            p = p.Parent
        End While
        Dim index As Integer = (From w In Content.Words Where w.Line < firstLineVisible).Count
        Dim count As Integer = 0

        For Each word In From w In Content.Words Where w.Line = firstLineVisible
            count += word.WordLength
            If count > x Then Exit For
            index += 1
        Next
        If index = SelectedIndex AndAlso Not x = Content.Words(index).LinePosition Then
            Return ForeColor
        Else
            Return BackColor
        End If
    End Function

    Protected Overrides Function GetForecolor(x As Integer, y As Integer) As ConsoleColor
        x -= ClientBounds.Left
        Dim p = Parent
        While p IsNot Nothing
            x -= p.ClientBounds.Left
            p = p.Parent
        End While
        Dim index As Integer = (From w In Content.Words Where w.Line < firstLineVisible).Count
        Dim count As Integer = 0
        For Each word In From w In Content.Words Where w.Line = firstLineVisible
            count += word.WordLength
            If count > x Then Exit For
            index += 1
        Next
        If index = SelectedIndex AndAlso Not x = Content.Words(index).LinePosition Then
            Return BackColor
        Else
            Return ForeColor
        End If
    End Function

    Protected Overridable Sub OnItemSelected(e As EventArgs)
        RaiseEvent ItemSelected(Me, e)
    End Sub

    Protected Overridable Sub OnSelectedIndexChanged(e As EventArgs)
        RaiseEvent SelectedIndexChanged(Me, e)
    End Sub

    Protected Overrides Sub OnShown(e As EventArgs)
        MyBase.OnShown(e)
        _SelectedIndex = 0
        firstLineVisible = 0
    End Sub

    Protected Overrides Sub OnPostDraw()
        MyBase.OnPostDraw()
        If indexChange IsNot Nothing Then
            Dim oldIndex = _SelectedIndex
            indexChange()
            indexChange = Nothing
            Window.ClearBackground(Me)
            Window.DrawText(Me)
            Window.ClearChildBackgrounds(Me.Children)
            If Not _SelectedIndex = oldIndex Then
                OnSelectedIndexChanged(EventArgs.Empty)
                oldIndex = _SelectedIndex
            End If
        End If
    End Sub

    Protected Overrides Sub UpdateInternalBounds()
        Dim b = Bounds
        If FrameVisible Then b.Height = 3 Else b.Height = 1
        _Bounds = b
        MyBase.UpdateInternalBounds()
    End Sub

    Private Sub ListWindow_KeyProcessing(sender As Object, e As KeyProcessingEventArgs) Handles Me.KeyProcessing
        Dim index As Integer = _SelectedIndex
        Dim canSuppress As Boolean = False
        Select Case e.Key.Key
            Case ConsoleKey.Enter
                OnItemSelected(EventArgs.Empty)
            Case ConsoleKey.LeftArrow
                indexChange = New Action(Sub() If _SelectedIndex > 0 Then _SelectedIndex -= 1)
                If _SelectedIndex > 0 Then index += -1
                canSuppress = True
            Case ConsoleKey.RightArrow
                indexChange = New Action(Sub() If _SelectedIndex < Content.WordCount - 1 Then _SelectedIndex += 1)
                If _SelectedIndex < Content.WordCount - 1 Then index += 1
                canSuppress = True
            Case ConsoleKey.UpArrow
                Dim w = Content.Words(_SelectedIndex)
                If w.Line - 1 >= 0 Then
                    Dim idx = _SelectedIndex
                    Dim pos = Content.Lines(w.Line - 1).TextPosition + Content.Lines(w.Line - 1).LineLength
                    While w.TextPosition + w.WordLength > pos AndAlso idx > 0
                        idx -= 1
                        w = Content.Words(idx)
                    End While
                    indexChange = New Action(Sub() _SelectedIndex = idx)
                End If
            Case ConsoleKey.DownArrow
                Dim w = Content.Words(_SelectedIndex)
                If w.Line + 1 < Content.LineCount Then
                    Dim idx = _SelectedIndex
                    Dim pos = Content.Lines(w.Line + 1).TextPosition
                    While w.TextPosition < pos
                        idx += 1
                        w = Content.Words(idx)
                    End While
                    indexChange = New Action(Sub() _SelectedIndex = idx)
                End If
        End Select

        If canSuppress Then
            If Content.Words(index)?.Line = firstLineVisible Then
                e.SuppressDefaultProcessing = True
            Else
                If e.Key.Key = ConsoleKey.LeftArrow Then
                    MyBase.ProcessKey(New ConsoleKeyInfo(" "c, ConsoleKey.UpArrow, False, False, False))
                Else
                    MyBase.ProcessKey(New ConsoleKeyInfo(" "c, ConsoleKey.DownArrow, False, False, False))
                End If
                e.SuppressDefaultProcessing = False
            End If
        End If

    End Sub
End Class
